package com.xinjian.service.impl;

import com.xinjian.base.config.Config;
import com.xinjian.base.enums.MsgActionEnum;
import com.xinjian.base.enums.MsgSignFlagEnum;
import com.xinjian.base.enums.SearchFriendsStatusEnum;
import com.xinjian.base.utils.*;
import com.xinjian.mapper.*;
import com.xinjian.netty.ChatMsg;
import com.xinjian.netty.DataContent;
import com.xinjian.netty.UserChannelRel;
import com.xinjian.pojo.FriendsRequest;
import com.xinjian.pojo.MyFriends;
import com.xinjian.pojo.Users;
import com.xinjian.pojo.vo.FriendRequestVO;
import com.xinjian.pojo.vo.MyFriendsVO;
import com.xinjian.service.UserService;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

import java.util.Date;
import java.util.List;


/**
 * app用户
 *
 * @author yyb
 * @create 2018-12-03-20:31
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    QRCodeUtils qrCodeUtils;

    @Autowired
    private FastDFSClient fastDFSClient;

    @Autowired
    private MyFriendsMapper myFriendsMapper;

    @Autowired
    private UsersMapperCustom usersMapperCustom;

    @Autowired
    private FriendsRequestMapper friendsRequestMapper;

    @Autowired
    private ChatMsgMapper chatMsgMapper;

    @Autowired
    private Config config;

    /**
     * @param userName
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Boolean queryUserNameIsExist(String userName) {
        Users user = new Users();
        user.setUserName(userName);
        Users result = usersMapper.selectOne(user);
        return result != null ? true : false;
    }


    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Users queryUserForLogin(String userName, String pwd) throws Exception {
        Example userExample = new Example(Users.class);
        Criteria criteria = userExample.createCriteria();
        criteria.andEqualTo("userName", userName);
        criteria.andEqualTo("passWord", MD5Utils.getMD5Str(pwd));
        Users result = usersMapper.selectOneByExample(userExample);
        return result;
    }

    @Transactional
    @Override
    public Users save(Users user) throws Exception {
        String userId = Sid.nextShort();
        user.setNickName(user.getUserName());
        user.setFaceImage("");
        user.setFaceImageBig("");
        user.setPassWord(MD5Utils.getMD5Str(user.getPassWord()));
        //为用户生成唯一的二维码
        //xinjian_qrcode:[userName]
        String qrcodePath = config.getUploadLocalPath() + config.getQrcodePrefix() + userId + config.getQrcodeSuffix();
        qrCodeUtils.createQRCode(qrcodePath, config.getQrcodeContent()+":" + user.getUserName());
        MultipartFile qrCodeFile = FileUtils.fileToMultipart(qrcodePath);
        String qrCodeUrl = "";
        try {
            qrCodeUrl = fastDFSClient.uploadBase64(qrCodeFile);
        } catch (Exception e) {
            e.fillInStackTrace();
        }
        user.setQrcode(qrCodeUrl);
        user.setId(userId);
        usersMapper.insert(user);
        return user;
    }

    @Transactional
    @Override
    public Users updateUsersInfo(Users user) {
        usersMapper.updateByPrimaryKeySelective(user);
        return queryUsersById(user.getId());
    }


    @Transactional(propagation = Propagation.SUPPORTS)
    protected Users queryUsersById(String userId) {
        return usersMapper.selectByPrimaryKey(userId);
    }

    /**
     * 搜索朋友的前置条件
     *
     * @param myUserId
     * @param friendUserName
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Integer preconditionSearchFriends(String myUserId, String friendUserName) {
        //1.搜索的用户不存在，返回【无此用户】
        Users user = queryUserInfonByUserName(friendUserName);
        if (user == null) {
            return SearchFriendsStatusEnum.USER_NOT_EXIST.status;
        }
        //2.搜索的账号是自己，返回【不能添加自己】
        if (user.getId().equals(myUserId)) {
            return SearchFriendsStatusEnum.NOT_YOURSELF.status;
        }
        //3.搜索的用户已经是你的好友，返回【该用户已经是你的好友】
        Example mfe = new Example(MyFriends.class);
        Criteria mfc = mfe.createCriteria();
        mfc.andEqualTo("myUserId", myUserId);
        mfc.andEqualTo("myFriendUserId", user.getId());
        MyFriends myFriendsRel = myFriendsMapper.selectOneByExample(mfe);
        if (myFriendsRel != null) {
            return SearchFriendsStatusEnum.ALREADY_FRIENDS.status;
        }
        return SearchFriendsStatusEnum.SUCCESS.status;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Users queryUserInfonByUserName(String userName) {
        Example userExample = new Example(Users.class);
        Criteria criteria = userExample.createCriteria();
        criteria.andEqualTo("userName", userName);
        return usersMapper.selectOneByExample(userExample);
    }

    /**
     * 添加好友请求记录，保存到数据库
     *
     * @param myUserId
     * @param friendUserName
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void sendFriendRequest(String myUserId, String friendUserName) {
        // 根据用户名把朋友信息查询出来
        Users friend = queryUserInfonByUserName(friendUserName);

        // 1. 查询发送好友请求记录表
        Example fre = new Example(FriendsRequest.class);
        Criteria frc = fre.createCriteria();
        frc.andEqualTo("sendUserId", myUserId);
        frc.andEqualTo("acceptUserId", friend.getId());
        FriendsRequest friendRequest = friendsRequestMapper.selectOneByExample(fre);
        if (friendRequest == null) {
            // 2. 如果不是你的好友，并且好友记录没有添加，则新增好友请求记录
            String requestId = Sid.nextShort();

            FriendsRequest request = new FriendsRequest();
            request.setId(requestId);
            request.setSendUserId(myUserId);
            request.setAcceptUserId(friend.getId());
            request.setRequestDateTime(new Date());
            friendsRequestMapper.insert(request);
        }
    }


    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<MyFriendsVO> queryMyFriends(String userId) {
        List<MyFriendsVO> myFriendsVOS = usersMapperCustom.queryMyFriends(userId);
        return myFriendsVOS;
    }


    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<FriendRequestVO> queryFriendRequestList(String acceptUserId) {
        return usersMapperCustom.queryFriendRequestList(acceptUserId);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void deleteFriendRequest(String sendUserId, String acceptUserId) {
        Example fre = new Example(FriendsRequest.class);
        Criteria frc = fre.createCriteria();
        frc.andEqualTo("sendUserId", sendUserId);
        frc.andEqualTo("acceptUserId", acceptUserId);
        friendsRequestMapper.deleteByExample(fre);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void passFriendRequest(String sendUserId, String acceptUserId) {
        //1.保存好友；
        saveFriends(sendUserId, acceptUserId);
        //2.逆向保存；
        saveFriends(acceptUserId, sendUserId);
        //3.删除好友请求
        deleteFriendRequest(sendUserId, acceptUserId);

        Channel sendChannel = UserChannelRel.get(sendUserId);
        if (sendChannel != null) {
            //使用webSocket主动推送消息到请求发起者，更新他的通信录列表为最新
            DataContent dataContent = new DataContent();
            dataContent.setAction(MsgActionEnum.PULL_FRIEND.type);

            sendChannel.writeAndFlush(new TextWebSocketFrame(
                    JsonUtils.objectToJson(dataContent)));
        }


    }


    @Transactional(propagation = Propagation.REQUIRED)
    protected void saveFriends(String sendUserId, String acceptUserId) {
        MyFriends myFriends = new MyFriends();
        myFriends.setId(Sid.nextShort());
        myFriends.setMyUserId(sendUserId);
        myFriends.setMyFriendUserId(acceptUserId);
        myFriendsMapper.insert(myFriends);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public String saveMsg(ChatMsg chatMsg) {
        com.xinjian.pojo.ChatMsg msgDB = new com.xinjian.pojo.ChatMsg();
        msgDB.setId(Sid.nextShort());
        msgDB.setAcceptUserId(chatMsg.getReceiverId());
        msgDB.setSendUserId(chatMsg.getSenderId());
        msgDB.setCreateTime(new Date());
        msgDB.setSignFlag(MsgSignFlagEnum.UNSIGN.getType());
        msgDB.setMsg(chatMsg.getMsg());
        chatMsgMapper.insert(msgDB);
        return msgDB.getId();
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void updateMsgSigned(List<String> msgIdList) {
        usersMapperCustom.batchUpdateMsgSigned(msgIdList);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<com.xinjian.pojo.ChatMsg> getUnReadMsgList(String acceptUserId) {
        Example chatExample = new Example(com.xinjian.pojo.ChatMsg.class);
        Criteria chatCriteria = chatExample.createCriteria();
        chatCriteria.andEqualTo("signFlag", 0);
        chatCriteria.andEqualTo("acceptUserId", acceptUserId);

        List<com.xinjian.pojo.ChatMsg> result = chatMsgMapper.selectByExample(chatExample);

        return result;
    }

}
